﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace MuXue.Zyiz.Template.Domain.IRepository
{
    public interface IRepository<T> where T : class
    {

        #region 新增

        /// <summary>
        /// 新增实体
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="IsCommit"></param>
        T AddEntity(T entity, bool IsCommit = true);

        /// <summary>
        /// 异步新增实体
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="IsCommit"></param>
        /// <returns></returns>
        Task<T> AddEntityAsync(T entity, bool IsCommit = true);

        /// <summary>
        /// 新增实体列表
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="IsCommit"></param>
        /// <returns></returns>
        int AddRange(IEnumerable<T> entity, bool IsCommit = true);

        /// <summary>
        /// 异步新增实体列表
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="IsCommit"></param>
        /// <returns></returns>
        Task  AddRangeAsync(IEnumerable<T> entity, bool IsCommit = true);

        #endregion

        #region 删除

        /// <summary>
        /// 删除实体
        /// </summary>
        /// <param name="where"></param>
        /// <param name="IsCommit"></param>
        /// <returns></returns>
        int DelEntity(Expression<Func<T, bool>> where, bool IsCommit = true);
        /// <summary>
        /// 删除实体
        /// </summary>
        /// <param name="where"></param>
        /// <param name="IsCommit"></param>
        /// <returns></returns>
        Task<int> DelEntityAsync(Expression<Func<T, bool>> where, bool IsCommit = true);
        #endregion

        #region 修改

        /// <summary>
        /// 修改实体
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="IsCommit"></param>
        /// <returns></returns>
        int UpdateEntity(T entity, bool IsCommit = true);

        /// <summary>
        /// 修改实体-异步
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="IsCommit"></param>
        /// <returns></returns>
        Task<int> UpdateEntityAsync(T entity, bool IsCommit = true);

        /// <summary>
        /// 更新部分字段
        /// </summary>
        int UpdateEntity(T entity, Expression<Func<T, object>>[] updatedProperties, bool IsCommit = true);
        /// <summary>
        /// 更新部分字段--孟老师
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="updatedProperties"></param>
        /// <param name="IsCommit"></param>
        /// <returns></returns>
        Task<int> UpdateEntityAsync(T entity, Expression<Func<T, object>>[] updatedProperties, bool IsCommit = true);

        /// <summary>
        /// 批量修改实体
        /// </summary>
        /// <param name="where"></param>
        /// <param name="entity"></param>
        int UpdateEntityRange(IEnumerable<T> entity, bool IsCommit = true);
        /// <summary>
        /// 批量修改实体
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="IsCommit"></param>
        /// <returns></returns>
        Task<int> UpdateEntityRangeAsync(IEnumerable<T> entity, bool IsCommit = true);
        #endregion

        #region 查询

        /// <summary>
        /// 查询所有数据
        /// </summary>
        /// <returns></returns>
        List<T> LoadEntityAll();

        /// <summary>
        /// 异步查询所有数据
        /// </summary>
        /// <returns></returns>
        Task<List<T>> LoadEntityAllAsync();

        /// <summary>
        /// 根据条件查询实体列表
        /// </summary>
        /// <param name="where">lamda表达式</param>
        /// <returns></returns>
        IEnumerable<T> WhereLoadEntityEnumerable(Expression<Func<T, bool>> where);

        /// <summary>
        /// 根据条件查询实体列表不跟踪
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        List<T> WhereLoadEntityListAsNoTracking(Expression<Func<T, bool>> where);

        /// <summary>
        /// 异步根据条件查询实体列表不跟踪
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        Task<List<T>> WhereLoadEntityListAsNoTrackingAsync(Expression<Func<T, bool>> where);

        /// <summary>
        /// 根据加载实体
        /// </summary>
        /// <param name="where">lamda表达式</param>
        /// <returns></returns>
        T WhereLoadEntity(Expression<Func<T, bool>> where);

        /// <summary>
        /// 根据条件异步加载实体
        /// </summary>
        /// <param name="where">lamda表达式</param>
        /// <returns></returns>
        Task<T> WhereLoadEntityAsync(Expression<Func<T, bool>> where);

        /// <summary>
        /// 根据条件查询实体不跟踪
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        T WhereLoadEntityAsNoTracking(Expression<Func<T, bool>> where);

        /// <summary>
        /// 异步根据条件异步查询实体不跟踪
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        Task<T> WhereLoadEntityAsNoTrackingAsync(Expression<Func<T, bool>> where);

        /// <summary>
        /// 获取最大的一条数据
        /// </summary>
        /// <param name="order"></param>
        /// <returns></returns>
        T LoadEntityMaxSort(Expression<Func<T, int>> order);

        /// <summary>
        /// 异步获取最大的一条数据
        /// </summary>
        /// <param name="order"></param>
        /// <returns></returns>
        Task<T> LoadEntityMaxSortAsync(Expression<Func<T, int>> order);

        /// <summary>
        ///  Any 查找数据判断数据是否存在
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        bool AnyEntity(Expression<Func<T, bool>> where);

        /// <summary>
        ///  异步Any 查找数据判断数据是否存在
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        Task<bool> AnyEntityAsync(Expression<Func<T, bool>> where);

        #endregion



        #region 分页排序查询
        /// <summary>
        /// 加载自己定义排序分页实体列表
        /// </summary>
        /// <param name="where"></param>
        /// <param name="orderby"></param>
        /// <param name="asc">asc/desc</param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        IEnumerable<T> LoadEntityEnumerable(Expression<Func<T, bool>> where, Expression<Func<T, string>> orderby, string asc, int pageIndex, int pageSize);
        IEnumerable<T> LoadEntityEnumerable(Expression<Func<T, bool>> where, Expression<Func<T, int?>> orderby, string asc, int pageIndex, int pageSize);
        IEnumerable<T> LoadEntityEnumerable(Expression<Func<T, bool>> where, Expression<Func<T, DateTime?>> orderby, string asc, int pageIndex, int pageSize);
        IEnumerable<T> LoadEntityEnumerable(Expression<Func<T, bool>> where, Expression<Func<T, decimal?>> orderby, string asc, int pageIndex, int pageSize);
        IEnumerable<T> LoadEntityEnumerable(Expression<Func<T, bool>> where, Expression<Func<T, bool?>> orderby, string asc, int pageIndex, int pageSize);
        #endregion

        #region 异步分页排序查询
        /// <summary>
        /// 加载自己定义排序分页实体列表
        /// </summary>
        /// <param name="where"></param>
        /// <param name="orderby"></param>
        /// <param name="asc">asc/desc</param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        Task<List<T>> LoadEntityListAsync(Expression<Func<T, bool>> where, Expression<Func<T, string>> orderby, string asc, int pageIndex, int pageSize);
        Task<List<T>> LoadEntityListAsync(Expression<Func<T, bool>> where, Expression<Func<T, int?>> orderby, string asc, int pageIndex, int pageSize);
        Task<List<T>> LoadEntityListAsync(Expression<Func<T, bool>> where, Expression<Func<T, DateTime?>> orderby, string asc, int pageIndex, int pageSize);
        Task<List<T>> LoadEntityListAsync(Expression<Func<T, bool>> where, Expression<Func<T, decimal?>> orderby, string asc, int pageIndex, int pageSize);
        #endregion

        #region 求平均，求总计
        int? GetSum(Expression<Func<T, bool>> where, Expression<Func<T, int?>> sum);
        double? GetSum(Expression<Func<T, bool>> where, Expression<Func<T, double?>> sum);
        float? GetSum(Expression<Func<T, bool>> where, Expression<Func<T, float?>> sum);
        decimal? GetSum(Expression<Func<T, bool>> where, Expression<Func<T, decimal?>> sum);
        double? GetAvg(Expression<Func<T, bool>> where, Expression<Func<T, int?>> avg);
        double? GetAvg(Expression<Func<T, bool>> where, Expression<Func<T, double?>> avg);
        float? GetAvg(Expression<Func<T, bool>> where, Expression<Func<T, float?>> avg);
        decimal? GetAvg(Expression<Func<T, bool>> where, Expression<Func<T, decimal?>> avg);

        #endregion

        #region 查最大
        /// <summary>
        /// 查最大
        /// </summary>
        /// <param name="max"></param>
        /// <returns></returns>
        int? GetMax(Expression<Func<T, int?>> max);
        /// <summary>
        /// 查最大
        /// </summary>
        /// <param name="max"></param>
        /// <returns></returns>
        double? GetMax(Expression<Func<T, double?>> max);
        /// <summary>
        /// 查最大
        /// </summary>
        /// <param name="max"></param>
        /// <returns></returns>
        decimal? GetMax(Expression<Func<T, decimal?>> max);
        /// <summary>
        /// 查最大
        /// </summary>
        /// <param name="max"></param>
        /// <returns></returns>
        DateTime? GetMax(Expression<Func<T, DateTime?>> max);
        #endregion

        #region 查询实体数量
        /// <summary>
        /// 查询实体数量
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        int GetEntitiesCount(Expression<Func<T, bool>> where);

        /// <summary>
        /// 异步查询实体数量
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        Task<int> GetEntitiesCountAsync(Expression<Func<T, bool>> where);
        #endregion

        #region 执行SQL
        /// <summary>
        /// 执行SQL语句
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        int ExecuteSql(string sql, object[] parameters = null);
        /// <summary>
        /// 执行SQL查询-返回List
        /// </summary>
        IEnumerable<Entity> QueryBySql<Entity>(string sql, object[] parameters = null);
        /// <summary>
        /// 使用sql脚本查询实体列表（分页）--带参数
        /// </summary>
        /// <returns></returns>
        IEnumerable<Entity> QueryBySqlRowNum<Entity>(string sqlString, string selectFields, string sortString, int pageSize, int pageIndex, ref int recordCount, object[] parameters = null);
        /// <summary>
        /// 执行sql语句，获取一个实体
        /// </summary>
        /// <typeparam name="Entity"></typeparam>
        /// <param name="sql"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        Entity QueryEntityBySql<Entity>(string sql, object[] parameters = null);

        #endregion
        /// <summary>
        /// 执行sql语句，获取一个string 或者其他单个类型的对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="sql"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        T QueryTBySql<T>(string sql, object[] parameters = null);

    }
}
